from vnpy.app.cta_strategy import (
    CtaTemplate,
    StopOrder,
    TickData,
    BarData,
    TradeData,
    OrderData,
    BarGenerator,
    ArrayManager,
)
import pandas as pd
import numpy as np
import time
from collections import OrderedDict
import math
import itertools
import gzip
import pickle
import os
import functools
import dask
from dask import compute, delayed
from dask.diagnostics import ProgressBar
import warnings
################################################################ for data init
class LinearSol:
    def __init__(self,turnover,qty,lowPrice,highPrice,multiplier):
        self.low = 0.0
        self.high = 0.0
        if lowPrice == highPrice:
            self.low = qty/2
            self.high = qty/2
        else:
            self.low = (turnover-qty*highPrice*multiplier)/(lowPrice-highPrice)/multiplier
            self.high = (turnover-qty*lowPrice*multiplier)/(highPrice-lowPrice)/multiplier

def isWholeNum(num):
    if num%1.0 == 0:
        return True
    else:
        return False

def setTrade(data,i):
    preTick = data.iloc[i-1,:]
    tick = data.iloc[i,:]
    sellTrade = 0.0
    sell2Trade = 0.0
    buyTrade = 0.0
    buy2Trade = 0.0
    ##############
    product_info = {}
    product_info['rb']= OrderedDict({'spread': 1,'int.factor': 1,'multiplier': 10})

    product = 'rb'
    multiplier = product_info[product]['multiplier']
    spread = product_info[product]['spread']
    intFactor = product_info['rb']['int.factor']
    intSpread = intFactor*spread
    
    result = LinearSol(tick['turnover'], tick['qty'],preTick['bid'], preTick['ask'], multiplier)
    done = False
    if isWholeNum(result.low) and isWholeNum(result.high) and result.low >= 0 and result.high >= 0:
        sellTrade = result.low
        buyTrade = result.high
        done = True
    else:
        price = 1.0*tick['turnover']/multiplier/tick['qty']
        if isWholeNum(price/spread):
            if price == preTick['bid']:
                sellTrade = tick['qty']
            elif price < preTick['bid']:
                sell2Trade = tick['qty']
            elif price == preTick['ask']:
                buyTrade = tick['qty']
            elif price > preTick['ask']:
                buy2Trade = tick['qty']
            else:
                sellTrade = tick['qty']/2
                buyTrade = tick['qty']/2
            done = True
        else:
            priceInt = 1.0*price * intFactor
            upInt = math.ceil(priceInt)
            loInt = math.floor(priceInt)
            if intSpread >1:
                loInt -= (loInt% intSpread)
                upInt = loInt + intSpread
            loPrice = loInt*1.0/intFactor
            upPrice = upInt*1.0/intFactor
            result2 = LinearSol(tick['turnover'],tick['qty'],loPrice,upPrice,multiplier)
            if result2.low >= 0 and result2.high >= 0 and result2.low+result2.high==tick['qty']:
                if price>preTick['bid'] and price<preTick['ask']:
                    sellTrade = result2.low
                    buyTrade = result2.high
                    done = True
                elif price >= preTick['ask']:
                    buyTrade = result2.low
                    buy2Trade = result2.high
                    done = True
                elif price <= preTick['bid']:
                    sell2Trade = result2.low
                    sellTrade = result2.high
                    done = True
    if done is False:
        if tick['ask']-tick['bid']==spread:
            if tick['mid']>preTick['mid']:
                result2 = LinearSol(tick['turnover'],tick['qty'],tick['bid'],tick['ask'],multiplier)
                buyTrade = result2.low
                buy2Trade = result2.high
            elif tick['mid'] < preTick['mid']:
                result2 = LinearSol(tick['turnover'],tick['qty'],tick['bid'],tick['ask'],multiplier)
                sell2Trade = result2.low
                sellTrade = result2.high
            else:
                if tick['price'] >= tick['ask']:
                    result2 = LinearSol(tick['turnover'],tick['qty'],tick['ask'],tick['ask']+spread,multiplier)
                    buyTrade = result2.low
                    buy2Trade = result2.high
                elif tick['price'] <= tick['bid']:
                    result2 = LinearSol(tick['turnover'],tick['qty'],tick['bid']-spread,tick['bid'],multiplier)
                    sell2Trade = result2.low
                    sellTrade = result2.high
        else: # spread > minimum
            if tick['ask'] > preTick['ask']:
                result2 = LinearSol(tick['turnover'],tick['qty'],preTick['ask'],tick['ask'],multiplier)
                buyTrade = result2.low
                buy2Trade = result2.high
            elif tick['bid'] < preTick['bid']:
                result2 = LinearSol(tick['turnover'],tick['qty'],tick['bid'],preTick['bid'],multiplier)
                sell2Trade = result2.low
                sellTrade = result2.high
    return buyTrade,buy2Trade,sellTrade,sell2Trade

def data_setTrade(data):
    buyList = []
    buy2List = []
    sellList = []
    sell2List = []
    for i,tickData in (data.iterrows()):
        if i == 0:
            buyTrade,buy2Trade,sellTrade,sell2Trade = (0,0,0,0)
        else:
            buyTrade,buy2Trade,sellTrade,sell2Trade = setTrade(data,i)
        buyList.append(buyTrade)
        buy2List.append(buy2Trade)
        sellList.append(sellTrade)
        sell2List.append(sell2Trade)
    print(len(buyList))
    data['buy_trade'] = buyList
    data['buy2_trade'] = buy2List
    data['sell_trade'] = sellList
    data['sell2_trade'] = sell2List
    return data

def zero_divide(x, y):
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        res = np.divide(x,y)
    if hasattr(y, "__len__"):
        res[y == 0] = 0
    elif y == 0:
        res = 0
    return res

def fast_roll_var(x, period):
      x_ma = cum(x,period)/period
      x2 = x*x
      x2_ma = cum(x2,period)/period
      var_x = x2_ma-x_ma*x_ma
      return(var_x)
    
def get_range_pos(wpr, min_period, max_period, period):
    return ewma(zero_divide(wpr-min_period, max_period-min_period), period, adjust=True) - 0.5

def vanish_thre(x, thre):
    x[np.abs(x)>thre] = 0
    return x

def cum(x, n):
    sum_x = x.cumsum()
    sum_x_shift = sum_x.shift(n)
    sum_x_shift[:n]= 0
    return sum_x - sum_x_shift

def ewma(x,shortlambda=0.000169211,init=0, adjust=False):
    init_s = pd.Series(data=init)
    s = init_s.append(x)
    if adjust:
        xx = range(len(x))
        aa=1-np.power(1-shortlambda, xx)*(1-shortlambda)
        bb=s.ewm(alpha=shortlambda, adjust=False).mean().iloc[1:]
        return bb/aa
    else:
        return s.ewm(alpha=shortlambda, adjust=False).mean()[1:]

def build_comp(data, period,dire_signal,range_signal):
    return (data[dire_signal+str(period)]*data[range_signal+str(period)]).values

def total_trade_imb(data, period):
    return vanish_thre(zero_divide(ewma(data["buy_trade"]+data["buy2_trade"]-data["sell_trade"]-data["sell2_trade"], adjust=True), 
                       ewma(data["qty"], adjust=True)),1)

def trade_imb(data, period):
    return ewma(zero_divide(data["buy_trade"] - data["sell_trade"], data["buy_trade"] + data["sell_trade"]), adjust=True)

def nr(data, period):
    return zero_divide(ewma(data["ret"], adjust=True), ewma(data["ret"].abs(), adjust=True))

def dbook(data, period):
    diff_bid_qty = data["bidqty"] - data["bidqty"].shift()
    diff_bid_qty[0] = 0
    diff_ask_qty = data["askqty"] - data["askqty"].shift()
    diff_ask_qty[0] = 0
    return ewma(np.sign(diff_bid_qty)-np.sign(diff_ask_qty))

def range_pos(data, period):
    return (ewma(zero_divide(data["wpr"]-data["min4096"], data["max4096"]-data["min4096"]), adjust=True) - 0.5)

def price_osci(data, period):
    return zero_divide(
        ewma(data["wpr"], shortlambda=0.003375496, adjust=True)-ewma(data["wpr"], adjust=True), 
        data["max4096"]-data["min4096"]
    )

def ma_diff_10(data, period):
    return zero_divide(ewma(data["wpr"], shortlambda=0.001689175, adjust=True) - ewma(data["wpr"], adjust=True), data["wpr"])

def atr(data, period):
    return (data["max4096"]-data["min4096"])

def kdj_k(data, period):
    return ewma(
        (zero_divide(data["wpr"]-data["min4096"],data["max4096"]-data["min4096"])-0.5)*2, 
        shortlambda=0.0008459755, 
        adjust=True
    )

def kdj_j(data, period):
    return ewma(
        ewma((zero_divide(data["wpr"]-data["min4096"], data["max4096"]-data["min4096"])-0.5)*2, shortlambda=0.0008459755, adjust=True), 
        shortlambda=0.0008459755, adjust=True)

def std(data, period):
    return (np.sqrt(fast_roll_var(data["wpr"], period)))

def range_(data, period):
    return (data["max4096"]-data["min4096"])

def vol_open(data, period):
    return zero_divide(cum(data["qty"],period), cum(data["cum.openint"]/period,period))

def trend_index(data, period):
    aa = zero_divide(abs(data["wpr"]-data["wpr"].shift(period)), data["max4096"]-data["min4096"])
    aa[0:period]=0
    return aa
#################################################################################### for data updata
def ewma_(x,shortlambda=0.000169211,ewma_last=0, adjust=False):
    if adjust:
        aa=1-np.power(1-shortlambda, 80000)
        bb=ewma_last*(1-shortlambda)+x*shortlambda
        return bb/aa
    else:
        return ewma_last*(1-shortlambda)+x*shortlambda
    
def get_last(data1):
    return data1.tail(1)

def zero_divide_(x, y):
    if abs(y)>1e-6:
        res = x/y
    else:
        res = 0
    return res

def vanish_thre_(x, thre):
    if np.abs(x)>thre:
        x= 0
    return x

def build_comp_(data, period,dire_signal,range_signal):
    return (data[dire_signal+str(period)]*data[range_signal+str(period)])

#total_trade_imb
def total_trade_imb_(x,t_t_i1,t_t_i2):
    tt1 = ewma_(x["buy_trade"]+x["buy2_trade"]-x["sell_trade"]-x["sell2_trade"], ewma_last=t_t_i1, adjust=True)
    tt2 = ewma_(x["qty"], ewma_last=t_t_i2, adjust=True)
    return vanish_thre_(zero_divide_(tt1, tt2),1),tt1,tt2

#trade_imb
def trade_imb_(x, t_i):
    ti1 = ewma_(zero_divide_(x["buy_trade"] - x["sell_trade"], x["buy_trade"] + x["sell_trade"]), ewma_last=t_i,adjust=True)
    return ti1

#nr
def nr_(x, i_ret,i_ret_abs):
    t1 = ewma_(x["ret"], ewma_last=i_ret, adjust=True)
    t2 = ewma_(abs(x["ret"]), ewma_last=i_ret_abs, adjust=True)
    return zero_divide_(t1, t2),t1,t2

#dbook
def dbook_(x, last, i_db):
    diff_bid_qty = x["bidqty"] - last["bidqty"].values[0]
    diff_ask_qty = x["askqty"] - last["askqty"].values[0]
    return ewma_(np.sign(diff_bid_qty)-np.sign(diff_ask_qty),ewma_last=i_db)

#range_pos
def range_pos_(x, i_rp):
    rp = ewma_(zero_divide_(x["wpr"]-x["min4096"], x["max4096"]-x["min4096"]), ewma_last=i_rp, adjust=True)
    return rp- 0.5,rp

#price_osci
def price_osci_(x, i_po1, i_po2):
    ip1 = ewma_(x["wpr"], shortlambda=0.003375496, ewma_last=i_po1, adjust=True)
    ip2 = ewma_(x["wpr"], ewma_last=i_po2, adjust=True)
    return zero_divide_(
        ip1 - ip2, x["max4096"]-x["min4096"]
    ),ip1,ip2

#ma_diff
def ma_diff_10_(x, i_md1, i_md2):
    i1 = ewma_(x["wpr"], shortlambda=0.001689175, ewma_last=i_md1, adjust=True)
    i2 = ewma_(x["wpr"], ewma_last=i_md2, adjust=True)
    return zero_divide_(i1 - i2, x["wpr"]), i1, i2

#atr
def atr_(x):
    return (x["max4096"]-x["min4096"])

#kdj.k
def kdj_k_(x, kk):
    return ewma_(
        (zero_divide_(x["wpr"]-x["min4096"],x["max4096"]-x["min4096"])-0.5)*2, 
        shortlambda=0.0008459755, ewma_last=kk, adjust=True
    )

#kdj.j
def kdj_j_(x, kj1,kj2):
    k2 = ewma_((zero_divide_(x["wpr"]-x["min4096"], x["max4096"]-x["min4096"])-0.5)*2, shortlambda=0.0008459755, ewma_last=kj2, adjust=True)
    return ewma_(k2,shortlambda=0.0008459755, ewma_last=kj1, adjust=True).values[-1],k2

#std~~~~~~~~~~
def std_(wpr):
    return np.std(wpr)

#range__
def range__(max4096,min4096):
    return (max4096[-1] - min4096[-1])

#vol_open
def vol_open_(qty,cum_oi):
    return zero_divide_(np.sum(qty), np.sum(cum_oi/4096))
#trend_index
def trend_index_(wpr,max4096,min4096):
    dd = zero_divide_(abs(wpr[-1]-wpr[0]), max4096[-1]-min4096[-1])
    return dd

class MultiFactorStrategy(CtaTemplate):
    """"""

    author = "用Python的交易员"

    #parameters
    atr_length = 22
    atr_ma_length = 10
    rsi_length = 5
    rsi_entry = 16
    trailing_percent = 0.8
    fixed_size = 1

    #variables

    parameters = ["atr_length", "atr_ma_length", "rsi_length",
                  "rsi_entry", "trailing_percent", "fixed_size"]
    variables = ["atr_value", "atr_ma", "rsi_value", "rsi_buy", "rsi_sell"]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)
        self.bg = BarGenerator(self.on_bar)
        self.am = ArrayManager()
        #计算volume,turnover change
        self.last_tick = None
        self.df_tmp = None

        self.data = []
        self.max4096 = np.zeros(4096)
        self.min4096 = np.zeros(4096)
        self.cum_oi = np.zeros(4096)
        self.qty = np.zeros(4096)
        self.wpr = np.zeros(4096)

        self.tick_lastprice = np.zeros(2)
        self.tick_turnover = np.zeros(2)
        self.tick_bid = np.zeros(2)
        self.tick_bidqty = np.zeros(2)
        self.tick_ask = np.zeros(2)
        self.tick_askqty = np.zeros(2)
        self.tick_wpr = np.zeros(2)
        self.tick_midprice = np.zeros(2)
        self.tick_ret = np.zeros(2)
        self.tick_buy_trade = np.zeros(2)
        self.tick_buy2_trade = np.zeros(2)
        self.tick_sell_trade = np.zeros(2)
        self.tick_sell2_trade = np.zeros(2)

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_tick(1)

        data = pd.read_csv('D:/intern/cppTrain/original/rb/20190826.csv',encoding='GBK',header=0,
                   names=["market","symbol","datetime","lastprice",
                          "cum.openint","openint","turnover","qty",
                          "open","close","type","direction","bid",
                          "ask","bidqty","askqty"])
        data = data.drop(['market','open','close','type','direction','openint'],axis=1)
        data = data[(data.askqty + data.bidqty != 0) & (data.ask + data.bid != 0)]
        data = data.reset_index(drop=True)

        data['wpr'] = (data['ask']*data['bidqty'] + data['bid']*data['askqty'])/(data['bidqty'] + data['askqty'])
        data['midprice'] = data['ask'].values*0.5 + data['bid'].values*0.5
        data.loc[data['wpr'] == 0,'wpr'] = data[data['wpr'] == 0]['midprice']
        # data['logprice'] = np.log(data['wpr'])
        data['ret'] = np.log(data['wpr']) - np.log(data['wpr'].shift())
        data['max4096'] = data['wpr'].rolling(4096).max()
        data['min4096'] = data['wpr'].rolling(4096).min()
        data = data_setTrade(data)
        data = data.fillna(0)

        data['total_trade_imb4096'] = total_trade_imb(data,4096)
        data['trade_imb4096'] = trade_imb(data,4096)
        data['nr4096'] = nr(data,4096)
        data['dbook4096'] = dbook(data,4096)
        data['range_pos4096'] = range_pos(data,4096)
        data['price_osci4096'] = price_osci(data,4096)
        data['ma_dif_104096'] = ma_diff_10(data,4096)
        data['atr4096'] = atr(data,4096)
        data['kdj_k4096'] = kdj_k(data,4096)
        data['kdj_j4096'] = kdj_j(data,4096)
        data['std4096'] = std(data,4096)
        data['range4096'] = range_(data,4096)
        data['vol_open4096'] = vol_open(data,4096)
        data['trend_index4096'] = trend_index(data,4096)

        dire_signal_list = ["total_trade_imb", "trade_imb", "nr", "dbook", "range_pos", "price_osci", "ma_dif_10", "kdj_k", "kdj_j"]
        range_signal_list = ["range", "std", "vol_open", "trend_index"]

        for range_signal in range_signal_list:
            for dire_signal in dire_signal_list:
                data[dire_signal+'.'+range_signal+'4096'] = build_comp(data, 4096,dire_signal,range_signal)
        #total_trade_imb
        self.t_t_i1 = ewma(data["buy_trade"]+data["buy2_trade"]-data["sell_trade"]-data["sell2_trade"], adjust=True).values[-1]
        self.t_t_i2 = ewma(data["qty"], adjust=True).values[-1]
        #trade_imb
        self.t_i = ewma(zero_divide(data["buy_trade"] - data["sell_trade"], data["buy_trade"] + data["sell_trade"])).values[-1]
        #nr
        self.i_ret = ewma(data['ret'], adjust=True).values[-1]
        self.i_ret_abs = ewma(data["ret"].abs(), adjust=True).values[-1]
        #dbook
        self.i_db = data['dbook4096'].values[-1]
        #range_pos
        self.i_rp = ewma(zero_divide(data["wpr"]-data["min4096"], data["max4096"]-data["min4096"]), adjust=True).values[-1]
        #price_osci
        self.i_po1 = ewma(data["wpr"], shortlambda=0.003375496, adjust=True).values[-1]
        self.i_po2 = ewma(data["wpr"], adjust=True).values[-1]
        #ma_diff
        self.i_md1 = ewma(data["wpr"], shortlambda=0.001689175, adjust=True).values[-1]
        self.i_md2 = ewma(data["wpr"], adjust=True).values[-1]
        #atr

        #kdj.k
        self.kk = data['kdj_k4096'].values[-1]
        #kdj.j
        self.kj1 = data['kdj_j4096']
        self.kj2 = ewma((zero_divide(data["wpr"]-data["min4096"], data["max4096"]-data["min4096"])-0.5)*2, shortlambda=0.0008459755, adjust=True)
        #std
        #range__
        #vol_open
        #trend_index
        self.data = data
        self.tail = data.tail(1)
        
        #4096
        self.max4096 = np.array(data['max4096'][-4096:].to_list())
        self.min4096 = np.array(data['min4096'][-4096:].to_list())
        self.wpr = np.array(data['wpr'][-4096:].to_list())
        self.cum_oi = np.array(data['cum.openint'][-4096:].to_list())
        self.qty = np.array(data['qty'][-4096:].to_list())
        #2
        self.tick_lastprice = np.array(data['lastprice'][-2:].to_list())
        self.tick_turnover = np.array(data['turnover'][-2:].to_list())
        self.tick_bid = np.array(data['bid'][-2:].to_list())
        self.tick_bidqty = np.array(data['bidqty'][-2:].to_list())
        self.tick_ask = np.array(data['ask'][-2:].to_list())
        self.tick_askqty = np.array(data['askqty'][-2:].to_list())
        self.tick_wpr = np.array(data['wpr'][-2:].to_list())
        self.tick_midprice = np.array(data['midprice'][-2:].to_list())
        self.tick_ret = np.array(data['ret'][-2:].to_list())
        self.tick_buy_trade = np.array(data['buy_trade'][-2:].to_list())
        self.tick_buy2_trade = np.array(data['buy2_trade'][-2:].to_list())
        self.tick_sell_trade = np.array(data['sell_trade'][-2:].to_list())
        self.tick_sell2_trade = np.array(data['sell2_trade'][-2:].to_list())

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)
        #计算volume turnover change
        if self.last_tick:
            volume_change = tick.volume - self.last_tick.volume
            turnover_change = tick.turnover - self.last_tick.turnover
        else:
            volume_change = tick.volume
            turnover_change = tick.turnover
        
        #update tick array
        self.max4096[:-1] = self.max4096[1:]
        self.min4096[:-1] = self.min4096[1:]
        self.wpr[:-1] = self.wpr[1:]
        self.cum_oi[:-1] = self.cum_oi[1:]
        self.qty[:-1] = self.qty[1:]

        self.max4096[-1] = tmp_max4096
        self.min4096[-1] = tmp_min4096
        self.wpr[-1] = tmp_wpr
        self.cum_oi[-1] = tick.open_interest
        self.qty[-1] = volume_change

        if self.df_tmp:
            self.tail = self.df_tmp.tail(1)
        
        df_tmp = pd.DataFrame({'symbol':tick.symbol,
                            'datetime':tick.datetime,
                            'lastprice':tick.last_price,
                            'cum.openint':tick.open_interest,
                            'turnover':turnover_change,
                            'qty':volume_change,
                            'ask':tick.ask_price_1,
                            'bid':tick.bid_price_1,
                            'askqty':tick.ask_volume_1,
                            'bidqty':tick.bid_volume_1})

        #筛选0值tick
        if not ((tick.ask_price_1 + tick.bid_price_1 > 0) & (tick.ask_volume_1 + tick.bid_volume_1 > 0)):
            return
        #wpr
        if tick.ask_price_1 * tick.bid_price_1 > 0:
            tmp_wpr = (tick.ask_price_1 * tick.bid_volume_1 + tick.bid_price_1 * tick.ask_volume_1) / (tick.ask_volume_1 + tick.bid_volume_1)
        else:
            tmp_wpr = tick.ask_price_1 * 0.5 + tick.bid_price_1 * 0.5
        df_tmp['wpr'] = tmp_wpr
        #midprice
        tmp_midprice = tick.ask_price_1 * 0.5 + tick.bid_price_1 * 0.5
        df_tmp['midprice'] = tmp_midprice
        #ret
        tmp_ret = np.log(tmp_wpr) - np.log(self.tick_wpr[-1])
        df_tmp['ret'] = tmp_ret
        #max4096 min4096
        if self.max4096[-1] >= tmp_wpr:
            tmp_max4096 = self.max4096[-1]
        elif self.max4096[-1] < tmp_wpr:
            tmp_max4096 = tmp_wpr
        df_tmp['max4096'] = tmp_max4096
        if self.min4096[-1] <= tmp_wpr:
            tmp_min4096 = self.min4096[-1]
        elif self.min4096[-1] > tmp_wpr:
            tmp_min4096 = tmp_wpr
        df_tmp['min4096'] = tmp_min4096
        #trade
        df = self.tail.append(df_tmp,ignore_index=True)
        df_trade = data_setTrade(df)
        df_tmp['buy_trade'] = df_trade['buy_trade'].values[-1]
        df_tmp['buy2_trade'] = df_trade['buy2_trade'].values[-1]
        df_tmp['sell_trade'] = df_trade['sell_trade'].values[-1]
        df_tmp['sell2_trade'] = df_trade['sell2_trade'].values[-1]
        #basic factor
        df_tmp['total_trade_imb4096'],tt1,tt2 = total_trade_imb_(df_tmp, self.t_t_i1, self.t_t_i2)
        self.t_t_i1 = tt1
        self.t_t_i2 = tt2

        df_tmp['trade_imb4096'] = trade_imb_(df_tmp, self.t_i)
        self.t_i = df_tmp['trade_imb4096']
        
        df_tmp['nr4096'],t1,t2 = nr_(df_tmp, self.i_ret,self.i_ret_abs)
        self.i_ret = t1
        self.i_ret_abs = t2
        
        df_tmp['dbook4096'] = dbook_(df_tmp, self.data, self.i_db)
        self.i_db = df_tmp['dbook4096']
        
        df_tmp['range_pos4096'],rp = range_pos_(df_tmp,self.i_rp)
        self.i_rp = rp
        
        df_tmp['price_osci4096'],ip1,ip2= price_osci_(df_tmp, self.i_po1, self.i_po2)
        self.i_po1 = ip1
        self.i_po2 = ip2
        
        df_tmp['ma_dif_104096'],i1,i2 = ma_diff_10_(df_tmp, self.i_md1, self.i_md2)
        self.i_md1 = i1
        self.i_md2 = i2
        
        df_tmp['atr4096'] = atr_(df_tmp)
        
        df_tmp['kdj_k4096'] = kdj_k_(df_tmp,self.kk)
        self.kk = df_tmp['kdj_k4096']
        
        df_tmp['kdj_j4096'],k2 = kdj_j_(df_tmp,self.kj1,self.kj2)
        self.kj1 = df_tmp['kdj_j4096']
        self.kj2 = k2
        
        df_tmp['std4096'] = std_(self.wpr)
        
        df_tmp['range4096'] = range__(self.max4096,self.min4096)
        
        df_tmp['vol_open4096'] = vol_open_(self.qty,self.cum_oi)
        
        df_tmp['trend_index4096'] = trend_index_(self.wpr,self.max4096,self.min4096)
        
        #manual compound factor
        df_tmp['total_trade_imb.range4096'] = df_tmp['total_trade_imb4096']*df_tmp['range4096']
        df_tmp['trade_imb.range4096'] = df_tmp['trade_imb4096']*df_tmp['range4096']
        df_tmp['nr.range4096'] = df_tmp['nr4096']*df_tmp['range4096']
        df_tmp['dbook.range4096'] = df_tmp['dbook4096']*df_tmp['range4096']
        df_tmp['range_pos.range4096'] = df_tmp['range_pos4096']*df_tmp['range4096']
        df_tmp['price_osci.range4096'] = df_tmp['price_osci4096']*df_tmp['range4096']
        df_tmp['ma_dif_10.range4096'] = df_tmp['ma_dif_104096']*df_tmp['range4096']
        df_tmp['kdj_k.range4096'] = df_tmp['kdj_k4096']*df_tmp['range4096']
        df_tmp['kdj_j.range4096'] = df_tmp['kdj_j4096']*df_tmp['range4096']

        df_tmp['total_trade_imb.std4096'] = df_tmp['total_trade_imb4096']*df_tmp['std4096']
        df_tmp['trade_imb.std4096'] = df_tmp['trade_imb4096']*df_tmp['std4096']
        df_tmp['nr.std4096'] = df_tmp['nr4096']*df_tmp['std4096']
        df_tmp['dbook.std4096'] = df_tmp['dbook4096']*df_tmp['std4096']
        df_tmp['range_pos.std4096'] = df_tmp['range_pos4096']*df_tmp['std4096']
        df_tmp['price_osci.std4096'] = df_tmp['price_osci4096']*df_tmp['std4096']
        df_tmp['ma_dif_10.std4096'] = df_tmp['ma_dif_104096']*df_tmp['std4096']
        df_tmp['kdj_k.std4096'] = df_tmp['kdj_k4096']*df_tmp['std4096']
        df_tmp['kdj_j.std4096'] = df_tmp['kdj_j4096']*df_tmp['std4096']

        df_tmp['total_trade_imb.vol_open4096'] = df_tmp['total_trade_imb4096']*df_tmp['vol_open4096']
        df_tmp['trade_imb.vol_open4096'] = df_tmp['trade_imb4096']*df_tmp['vol_open4096']
        df_tmp['nr.vol_open4096'] = df_tmp['nr4096']*df_tmp['vol_open4096']
        df_tmp['dbook.vol_open4096'] = df_tmp['dbook4096']*df_tmp['vol_open4096']
        df_tmp['range_pos.vol_open4096'] = df_tmp['range_pos4096']*df_tmp['vol_open4096']
        df_tmp['price_osci.vol_open4096'] = df_tmp['price_osci4096']*df_tmp['vol_open4096']
        df_tmp['ma_dif_10.vol_open4096'] = df_tmp['ma_dif_104096']*df_tmp['vol_open4096']
        df_tmp['kdj_k.vol_open4096'] = df_tmp['kdj_k4096']*df_tmp['vol_open4096']
        df_tmp['kdj_j.vol_open4096'] = df_tmp['kdj_j4096']*df_tmp['vol_open4096']

        df_tmp['total_trade_imb.trend_index4096'] = df_tmp['total_trade_imb4096']*df_tmp['trend_index4096']
        df_tmp['trade_imb.trend_index4096'] = df_tmp['trade_imb4096']*df_tmp['trend_index4096']
        df_tmp['nr.trend_index4096'] = df_tmp['nr4096']*df_tmp['trend_index4096']
        df_tmp['dbook.trend_index4096'] = df_tmp['dbook4096']*df_tmp['trend_index4096']
        df_tmp['range_pos.trend_index4096'] = df_tmp['range_pos4096']*df_tmp['trend_index4096']
        df_tmp['price_osci.trend_index4096'] = df_tmp['price_osci4096']*df_tmp['trend_index4096']
        df_tmp['ma_dif_10.trend_index4096'] = df_tmp['ma_dif_104096']*df_tmp['trend_index4096']
        df_tmp['kdj_k.trend_index4096'] = df_tmp['kdj_k4096']*df_tmp['trend_index4096']
        df_tmp['kdj_j.trend_index4096'] = df_tmp['kdj_j4096']*df_tmp['trend_index4096']
        self.df_tmp = df_tmp.tail(1)
        print(df_tmp)

        self.last_tick = tick

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.cancel_all()

        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return
        
        self.put_event()

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
